﻿
using System;
using System.IO;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
using System.Collections.Generic;
using System.Text;

namespace Stanza.MSBuild.Tasks
{
    //
    // XML Schema:
    //
    //  <Publish>
    //    <Solution>SoultionFile.sln</Solution>
    //    <ZipFile Prefix="FileNamePrefix">C:\Releases\ReleaseFile.zip</ZipFile>
    //  </Publish>
    //
    // Paths are relative to the location of this file.
    //

    public class PublishInfo
    {
        private string fileName;
        private XDocument pubDoc;
        private List<PublishFile> publishFileList = new List<PublishFile>();

        private PublishInfo()
        {
        }

        public string FileName
        {
            get { return fileName; }
        }

        public string FilePath
        {
            get { return Path.GetDirectoryName( fileName ); }
        }

        public static PublishInfo Load( string fileName )
        {
            string fullName = Path.GetFullPath( fileName );
            if( !File.Exists( fullName ) )
                throw new FileNotFoundException( String.Concat( "Could not find: ", fullName ), fullName );

            XDocument pubDoc;
            using( StreamReader readStream = new StreamReader( fileName ) )
            using( XmlReader xmlReader = XmlReader.Create( readStream ) )
                pubDoc = XDocument.Load( xmlReader );

            PublishInfo pubInfo = new PublishInfo();
            pubInfo.fileName = fullName;
            pubInfo.pubDoc = pubDoc;
            return pubInfo;
        }

        public string SolutionFile
        {
            get
            {
                var q = pubDoc.XPathSelectElement( "/Publish/Solution" );
                if( ( q == null ) || String.IsNullOrEmpty( q.Value ) )
                    throw new InvalidPublishInfoData( "Could not find solution file name." );
                return Path.Combine( FilePath, q.Value );
            }
        }

        public string ZipFile
        {
            get
            {
                var q = pubDoc.XPathSelectElement( "/Publish/ZipFile" );
                if( ( q == null ) || String.IsNullOrEmpty( q.Value ) )
                    throw new InvalidPublishInfoData( "Could not find zip file name." );
                return Path.Combine( FilePath, q.Value );
            }
        }

        public string FileNamePrefix
        {
            get
            {
                var q = pubDoc.XPathSelectElement( "/Publish/ZipFile" );
                if( q == null )
                    return null;
                var a = q.Attribute( "Prefix" );
                if( ( a == null ) || String.IsNullOrEmpty( a.Value ) )
                    return null;
                return a.Value;
            }
        }

        public void AddPublishFile( PublishFile pubFile )
        {
            publishFileList.Add( pubFile );
        }

        public IEnumerable<PublishFile> GetFilesToPublish()
        {
            return publishFileList;
        }
    }

    public delegate Stream ModifyFile( Stream readStream );

    public class PublishFile
    {
        public string FileName { get; set; }
        public ModifyFile ModifyFile { get; set; }
    }
}
